package org.mozhu.zufang.admin.security;

import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.mozhu.zufang.system.account.entity.User;
import org.mozhu.zufang.system.account.service.UserService;
import org.mozhu.zufang.system.auth.service.AuthorityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.social.security.SocialUser;
import org.springframework.social.security.SocialUserDetails;
import org.springframework.social.security.SocialUserDetailsService;
import org.springframework.util.StringUtils;

import java.util.Collection;
import java.util.List;
import java.util.Set;

@Slf4j
public class CustomUserDetailsService implements UserDetailsService, SocialUserDetailsService {

    @Autowired
    UserService userService;

    @Autowired
    @Qualifier("authorityService")
    AuthorityService authorityService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userService.findByLoginName(username);
        if (user == null) {
            throw new UsernameNotFoundException("User of username[" + username + "] not found");
        }

        Collection<GrantedAuthority> authorities = authorities(user);
        return org.springframework.security.core.userdetails.User.builder()
                .username(user.getLoginName())
                .password(user.getPassword())
                .disabled(!user.getActivated())
                .authorities(authorities)
                .accountLocked(!user.isAvailable())
                .build();
    }

    private Collection<GrantedAuthority> authorities(User user) {
        List<GrantedAuthority> grantedAuthorityList = Lists.newArrayList();
        Set<String> roles = findStringRoles(user);
        log.info("Load Roles of User[{}]: {}", user.getLoginName(), roles);
        for (String role : roles) {
            grantedAuthorityList.add(new SimpleGrantedAuthority("ROLE_" + role));
        }
        Set<String> permissions = findStringPermissions(user);
        log.info("Load Permissions of User[{}]: {}", user.getLoginName(), permissions);
        for (String permission : permissions) {
            Set<String> permissionList = StringUtils.commaDelimitedListToSet(permission);
            for (String p : permissionList) {
                grantedAuthorityList.add(new SimpleGrantedAuthority(p));
            }
        }
        return grantedAuthorityList;
    }

    private Set<String> findStringPermissions(User user) {
        return authorityService.findStringPermissions(user.getId());
//        return Sets.newHashSet("system:user:add");
    }

    private Set<String> findStringRoles(User user) {
        return authorityService.findStringRoles(user.getId());
//        return Sets.newHashSet("ADMIN");
    }

    @Override
    public SocialUserDetails loadUserByUserId(String userId) throws UsernameNotFoundException {
        String username = userId;
        User user = userService.findByLoginName(username);
        if (user == null) {
            throw new UsernameNotFoundException("User of username[" + username + "] not found");
        }

        Collection<GrantedAuthority> authorities = authorities(user);
        return new SocialUser(user.getLoginName(), user.getPassword(), authorities);
    }
}
